package com.wxxymakers.cklabrecruit.config;

import com.wxxymakers.cklabrecruit.realm.AuthrcRealm;
import com.wxxymakers.cklabrecruit.service.UserService;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @AUTHOR soft
 * @DATE 2018/10/26 16:37
 * @DESCRIBE Shiro配置
 */
@Configuration
public class ShiroConfig {

    /**
     * shiro安全管理器bean
     *
     * @param realm 自定义的realm
     */
    @Bean("securityManager")
    public WebSecurityManager getSecurityManager(@Qualifier("authrcRealm") Realm realm,
                                                 EhCacheManagerFactoryBean ehCacheManagerFactoryBean) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
        ehCacheManager.setCacheManager(ehCacheManagerFactoryBean.getObject());
        securityManager.setCacheManager(ehCacheManager);
        CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
        rememberMeManager.getCookie().setMaxAge(7 * 3600 * 24); // 保存七天
        securityManager.setRememberMeManager(rememberMeManager);
        return securityManager;
    }

    /**
     * 自定义的realm
     *
     * @param md5Matcher 凭证验证器
     */
    @Bean("authrcRealm")
    public Realm getAuthrcRealm(CredentialsMatcher md5Matcher,
                                UserService userService) {
        AuthrcRealm realm = new AuthrcRealm();
        realm.setUserService(userService);
        realm.setCredentialsMatcher(md5Matcher);
        return realm;
    }

    /**
     * md5凭证验证器
     */
    @Bean("md5Matcher")
    public CredentialsMatcher getCredentialsMatcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");
        matcher.setHashIterations(101);
        return matcher;
    }

    /**
     * aop支持 使用cglib实现
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
        proxyCreator.setProxyTargetClass(true);
        return proxyCreator;
    }

    /**
     * shiro注解支持
     * @param securityManager 安全管理器
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(WebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    /**
     * Shiro过滤器
     * @param securityManager 安全管理器
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilter(WebSecurityManager securityManager) {
        ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
        filter.setSecurityManager(securityManager);
        filter.setLoginUrl("/login");
        filter.setSuccessUrl("/");
        filter.setUnauthorizedUrl("/unauth");
        Map<String, String> map = new LinkedHashMap<>();
        map.put("/verify", "anon");
        map.put("/access", "anon");
        map.put("/login", "anon");
        map.put("/register", "anon");
        map.put("/about", "anon");
        map.put("/video", "anon");
        map.put("/video/f", "anon");
        map.put("/", "anon");
        map.put("/home", "anon");
        map.put("/unauth", "anon");
        map.put("/static/**", "anon");
        map.put("/recruit/apply", "anon");
        map.put("/recruit/reapply", "anon");
        map.put("/email/return/t/**", "anon");
        map.put("/logout", "logout");
        map.put("/admin/**", "roles[admin]");
        map.put("/**", "user");

        filter.setFilterChainDefinitionMap(map);
        return filter;
    }
}
